package com.hifar.utils;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.text.SimpleDateFormat;
import java.util.*;

public class QRCodeUtil {
    /**
     * @param width    宽   建议值300
     * @param height   高  建议值300
     * @param filePath 图片的路径
     * @MethodName: generateQRCodeImage
     * @Description:生成二维码图片
     * @Param: * @param text 内容
     * @Return: String 图片路径
     * @Author: lyk
     * @Date: 15:01 2020/3/2
     **/
    public static String generateQRCodeImage(String text, int width, int height, String filePath) {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        try {
            MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
            Map hints = new HashMap<String, Object>();
            //设置UTF-8,防止中文乱码
            hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
            //设置二维码四周白色区域的大小
            hints.put(EncodeHintType.MARGIN, 4);
            //设置二维码的容错性
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            //画二维码，记得调用multiFormatWriter.encode()时最后要带上hints参数，不然上面设置无效
            BitMatrix bitMatrix = multiFormatWriter.encode(text, BarcodeFormat.QR_CODE, width, height, hints);
            //重新生成新的二维码保持大小一致,白色区域一致
            bitMatrix = updateBit(bitMatrix, 1);
            Path path = FileSystems.getDefault().getPath(filePath);
            MatrixToImageWriter.writeToFile(bitMatrix, "jpg", new File(filePath));
            return path.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return "失败";
        }
    }

    /**
     * @param width  宽 建议值300
     * @param height 高  建议值300
     * @MethodName: generateQRCodeImageBts
     * @Description: 生成二维码, 返回字节数组
     * @Param: * @param text 二维码的内容
     * @Return: byte[] 二维码字节数组
     * @Author: lyk
     * @Date: 15:03 2020/3/2
     **/
    public static byte[] generateQRCodeImageBts(String text, int width, int height) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        try {
            MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
            Map hints = new HashMap<String, Object>();
            //设置UTF-8,防止中文乱码
            hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
            //设置二维码四周白色区域的大小
            hints.put(EncodeHintType.MARGIN, 4);
            //设置二维码的容错性
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
            //画二维码，记得调用multiFormatWriter.encode()时最后要带上hints参数，不然上面设置无效
            BitMatrix bitMatrix = multiFormatWriter.encode(text, BarcodeFormat.QR_CODE, width, height, hints);
            //重新生成新的二维码保持大小一致,白色区域一致
            bitMatrix = updateBit(bitMatrix, 1);
            //将二维码转为stream
            MatrixToImageWriter.writeToStream(bitMatrix, "jpg", outputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return outputStream.toByteArray();
    }

    /**
     * @param title pdf的标题信息
     * @MethodName: generatePDFBts
     * @Description:生成pdf字节数组
     * @Param: * @param imageList 字节数组集合
     * @Return: byte[]
     * @Author: lyk
     * @Date: 16:13 2020/3/2
     **/
    public static byte[] generatePDFBts(ArrayList imageList, String title) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();//构建字节输出流
        Document doc = null;
        try {
            doc = new Document();//新建文档
            doc.setPageSize(new Rectangle(PageSize.A4));// 可配其余4个参数，如（rectPageSize，60,60,60,60）页面边距
            PdfWriter pdfWriter = PdfWriter.getInstance(doc, baos);//将PDF文档对象写入到流
            pdfWriter.setStrictImageSequence(true);//设置图片精确存放
            PdfPTable table = new PdfPTable(2);//添加表格 2列
            table.setHorizontalAlignment(Element.ALIGN_CENTER);//垂直居中
//            float[] wid1={0.4f,0.4f};//两列的宽度比例
//            table.setWidths(wid1);
//            table.getDefaultCell().setBorderWidth(1);//边框
            //判断是偶数还是奇数,0偶1奇,是奇数时size+1,否则最后1个二维码无法显示
            int index = imageList.size();
            int res = index % 2;
            if (res == 1) {
                index = imageList.size() + 1;
            }
            //遍历image字节数组集合
            for (int i = 0; i < imageList.size(); i++) {
                byte[] imageBts = (byte[]) imageList.get(i);//获取每个二维码字节数组
                PdfPCell cell = new PdfPCell();//定义单元格
                if (i == 0) {
                    Paragraph p = new Paragraph();//定义段落
                    p.setSpacingAfter(14f);//段落的后间距
                    cell.addElement(p);//将段落加入到单元格里
                }
                Image image = Image.getInstance(imageBts);//
//                image.scalePercent(75f);//缩放
                cell.addElement(image);
                image.setAbsolutePosition(250f, 250f);//固定大小
                cell.setBorder(0);//设置单元格边框
                cell.setPaddingTop(32f);//设置单元格上内边距
                cell.setPaddingLeft(10f);//设置单元格左内边距
//                cell.setFixedHeight(200f);
                table.addCell(cell);//添加单元格到table
                //当index>size,并且size-1==1,添加最后一个单元格,为了凑齐一行,显示最后1个落单的二维码
                if (index > imageList.size() && imageList.size() - i == 1) {
                    PdfPCell cellend = new PdfPCell();//定义单元格
                    cellend.setBorder(0);//设置单元格边框
                    cellend.setPaddingTop(32f);//
                    cellend.setPaddingLeft(10f);//
                    table.addCell(cellend);
                }
                /*如果出现某些行中的文本非常大，
                    那么iText将按照“行优先”的方式对表格进行分页处理，
                    所谓“行优先”是说：当遇到无法在当前页显示完整的一行时，
                    该行将被放到下一页进行显示，而只有当一整页都无法显示完此行时，
                    iText才会将此行拆开显示在两页中。如果不想使用“行优先”的方式，
                    而是想采用“页优先”方式（保证填满当前页面的前提下，决定是否需要分拆行）显示，
                    可使用方法setSplitLate(false)。*/
                table.setSplitLate(false);
                table.setSplitRows(true);
            }
            doc.open();//打开文档;
            //设置中文字体,这里需要itext-asian的jar
            BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
            //设置标题字体
            Font titleFont = new Font(bfChinese, 14, Font.NORMAL);
            Paragraph paragraph1 = new Paragraph(title, titleFont);
            //居中
            paragraph1.setAlignment(Element.ALIGN_CENTER);
            doc.add(paragraph1);//添加标题段落到文档
            doc.add(table);//添加表格到文档
            doc.close();//关闭文档
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (baos != null) {
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        byte[] PDFBts = baos.toByteArray();//pdf字节数组
        System.out.println("baos.toByteArray().length:" + baos.toByteArray().length);
        return PDFBts;
    }

    ;

    /**
     * @param margin 白色区域的大小
     * @MethodName: updateBit
     * @Description:将二维码重新生成为250*250的,固定宽高是为了保持二维码大小一致
     * @Param: * @param matrix 原来的二维码
     * @Return: com.google.zxing.common.BitMatrix
     * @Author: lyk
     * @Date: 14:53 2020/3/11
     **/
    private static BitMatrix updateBit(BitMatrix matrix, int margin) {
        int[] rec = matrix.getEnclosingRectangle();   //获取二维码图案的属性
        int tempM = margin * 2;
        int resWidth = rec[2] + tempM;
        int resHeight = rec[3] + tempM;
        BitMatrix resMatrix = new BitMatrix(resWidth, resHeight); // 按照自定义边框生成新的BitMatrix
        resMatrix.clear();
        for (int i = margin; i < resWidth - margin; i++) {   //循环，将二维码图案绘制到新的bitMatrix中
            for (int j = margin; j < resHeight - margin; j++) {
                if (matrix.get(i - margin + rec[0], j - margin + rec[1])) {
                    resMatrix.set(i, j);
                }
            }
        }
        return resMatrix;
    }

    /**
     * @MethodName: getRandomKey
     * @Description:生成年月日_时分秒_随机数格式的唯一码值 如:20200311_143741_82199615
     * @Param: * @param
     * @Return: java.lang.String
     * @Author: lyk
     * @Date: 14:57 2020/3/11
     **/
    public static String getRandomKey() {
        Date date = new Date();
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd_HHmmss");
        String dateStr = df.format(date);
        Random ran = new Random();
        int prefix = ran.nextInt(9000) + 1000;
        int suffix = ran.nextInt(9000) + 1000;
        return dateStr + "_" + String.valueOf(prefix) + String.valueOf(suffix);
    }
}
